#include "../udp_message_context.h"
#include "../udp_acceptor_config.h"
#include "../io_handler.h"
#include <string>

namespace vpm 
{
	namespace mina
	{
		namespace detail 
		{
			class AsioUdpAcceptorImpl 
			{

				public:
					enum 
					{
						UDP_MAX_RECV_BUF_LEN = 8192
					};

					AsioUdpAcceptorImpl(UdpAcceptorConfig &config, 
							IoHandler & handler ):m_udpConfig(config),
					m_ioHandler(handler)
					{

					}

					int bind(int port, const std::string & host = "0.0.0.0")
					{
						return 0; 
					}

					void unbind()
					{
					}

					int send_data(char * pData, int dataLen, 
							int peerPort, const std::string & peerHost)
					{
						m_udpSocket.send_to(boost::asio::buffer(pData,dataLen),
								tcp::endpoint(boost::asio::ip::address::from_string(host),port));
					}

					int send_data(MessageContext & msg)
					{
						UdpMessageContext & udpMsg = (UdpMessageContext&) msg; 
						return this->send_data(udpMsg.buffer,udpMsg.length, 
								udpMsg.port,udpMsg.get_host_addr());
					}

					int recv_data(MessageContext & msg)
					{
						udp::endpoint peerPoint; 
						UdpMessageContext & udpMsg = (UdpMessageContext&) msg; 
						udpMsg.length = m_udpSocket.receive_from(boost::asio::buffer(msg.buffer), 
								peerPoint); 
						udpMsg.set_host_addr(peerPoint.address().to_string());
						udpMsg.port = peerPoint.port(); 
						return udpMsg.length; 
					}

					int process_data(char * pData, int dataLen, int peerPort, 
							const std::string & peerHost)
					{
						IoFilterChain & chain =  m_udpConfig.get_input_chain(); 
						UdpMessageContext context(pData, dataLen, peerPort, peerHost); 
						chain.process(context); 
						return 0; 
					}


				private:
					boost::array<char, UDP_MAX_RECV_BUF_LEN> m_recvBuf; 
					boost::asio::io_service m_ioService; 
					udp::socket m_udpSocket; 
			}
#define UdpAcceptorImpl AsioUdpAcceptorImpl
		}
	}
}
